package com.ruibang.glass.sale.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.common.domain.DictInfo;
import com.ruibang.glass.common.domain.ProductInfo;
import com.ruibang.glass.common.domain.file.FileBusiness;
import com.ruibang.glass.common.domain.material.MaterialProductsOut;
import com.ruibang.glass.frequencycontrol.annotation.RedissonLock;
import com.ruibang.glass.sale.constant.Constants;
import com.ruibang.glass.sale.constant.SaleDisputeResultCode;
import com.ruibang.glass.sale.constant.SaleErrorCode;
import com.ruibang.glass.sale.constant.SaleMenuIdCode;
import com.ruibang.glass.sale.domain.req.GSaleReturnExchangeReq;
import com.ruibang.glass.sale.dto.FileInfoDTO;
import com.ruibang.glass.sale.entity.*;
import com.ruibang.glass.sale.feign.FileApi;
import com.ruibang.glass.sale.feign.MaterialApi;
import com.ruibang.glass.sale.feign.PortalApi;
import com.ruibang.glass.sale.mapper.*;
import com.ruibang.glass.sale.service.*;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.constant.CommonConstant;
import com.teaming.cloud.framework2.common.exception.ServiceException;
import com.teaming.cloud.framework2.common.model.ResultBody;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.ruibang.glass.common.constants.RedisKey.MATERIAL_IN_WAREHOUSE_NUMBER;


@Slf4j
@Service
public class GSaleReturnExchangeOrderServiceImpl extends ServiceImpl<GSaleReturnExchangeOrderMapper, GSaleReturnExchangeOrder> implements GSaleReturnExchangeOrderService {

    @Autowired
    private GSaleReturnExchangeOrderDetailMapper gSaleReturnExchangeOrderDetailMapper;

    @Autowired
    private GSaleReturnFileMapper gSaleReturnFileMapper;

    @Autowired
    private FileApi fileApi;
    @Autowired
    private PortalApi portalApi;
    @Autowired
    private MaterialApi materialApi;

    @Autowired
    private RedisSingleService rediservice;

    @Autowired
    private GSaleDisputeMapper saleDisputeMapper;

    @Autowired
    private GSaleReturnInventoryService saleReturnInventoryService;

    @Autowired
    private SaleShippingApplicationService saleShippingApplicationService;

    @Autowired
    private GSaleCustomerManagementMapper saleCustomerManagementMapper;

    @Override
    public IPage<GSaleReturnExchangeOrder> getPage(GSaleReturnExchangeReq gSaleReturnExchangeReq) {
        return baseMapper.getPage(new Page<>(gSaleReturnExchangeReq.getPageNo(), gSaleReturnExchangeReq.getPageSize()), gSaleReturnExchangeReq);

    }

    @Override
    public void addGSaleReturnExchangeOrder(GSaleReturnExchangeOrder gSaleReturnExchangeOrder) {

        if (CollectionUtils.isEmpty(gSaleReturnExchangeOrder.getGSaleReturnExchangeOrderDetails())) {
            throw new ServiceException(SaleErrorCode.SALE_RETURN_NO_PRODUCT.getCode(), SaleErrorCode.SALE_RETURN_NO_PRODUCT.getMsg());
        }
        Map<String, String> aTypeMap = new HashMap<>();
        for (GSaleReturnExchangeOrderDetail saleReturnExchangeOrderDetail : gSaleReturnExchangeOrder.getGSaleReturnExchangeOrderDetails()) {
            if (aTypeMap.get(saleReturnExchangeOrderDetail.getTrayId()) != null) {
                throw new ServiceException(SaleErrorCode.SAME_A_TYPE_DELETE.getCode(), SaleErrorCode.SAME_A_TYPE_DELETE.getMsg());
            }else {
                aTypeMap.put(saleReturnExchangeOrderDetail.getTrayId(),saleReturnExchangeOrderDetail.getTrayId());
            }
        }

        if (gSaleReturnExchangeOrder.getReturnType().equals(Constants.ONE_STR)) {
            gSaleReturnExchangeOrder.setIsStatus(Constants.TWO_STR);
        }
        baseMapper.insert(gSaleReturnExchangeOrder);
        BigDecimal totalCount = BigDecimal.ZERO;
        BigDecimal totalAmount = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(gSaleReturnExchangeOrder.getGSaleReturnExchangeOrderDetails())) {
            for (GSaleReturnExchangeOrderDetail gSaleReturnExchangeOrderDetail : gSaleReturnExchangeOrder.getGSaleReturnExchangeOrderDetails()) {
                if (gSaleReturnExchangeOrderDetail.getQuantity() != null && gSaleReturnExchangeOrderDetail.getReturnQuantity() == null) {
                    gSaleReturnExchangeOrderDetail.setReturnQuantity(gSaleReturnExchangeOrderDetail.getQuantity());
                }
                gSaleReturnExchangeOrderDetail.setId("");
                gSaleReturnExchangeOrderDetail.setReturnId(gSaleReturnExchangeOrder.getId());
                if (gSaleReturnExchangeOrderDetail.getReturnQuantity() != null) {
                    totalCount = totalCount.add(gSaleReturnExchangeOrderDetail.getReturnQuantity());
                }
                if (gSaleReturnExchangeOrderDetail.getReturnTotal() != null) {
                    totalAmount = totalAmount.add(gSaleReturnExchangeOrderDetail.getReturnTotal());
                }

                gSaleReturnExchangeOrderDetailMapper.insert(gSaleReturnExchangeOrderDetail);
            }
        }
        gSaleReturnExchangeOrder.setReturnQuantity(totalCount.intValue());
        gSaleReturnExchangeOrder.setRefundTotal(totalAmount.toString());
        baseMapper.updateById(gSaleReturnExchangeOrder);
        if (CollectionUtils.isNotEmpty(gSaleReturnExchangeOrder.getFilesIds())) {
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(gSaleReturnExchangeOrder.getFilesIds());
            fileBusiness.setBusinessId(gSaleReturnExchangeOrder.getId());
            fileApi.updateBusinessById(fileBusiness);
        }
        //判断异议单 同时生成发货单
        GSaleDispute gSaleDispute = saleDisputeMapper.selectById(gSaleReturnExchangeOrder.getDisputeId());
        if (gSaleReturnExchangeOrder.getReturnType().equals(Constants.TWO_STR) || gSaleReturnExchangeOrder.getReturnType().equals(Constants.ONE_STR)) {
            // 生成退货入库单
            saleReturnInventoryService.saveGSaleReturnInventory(getGSaleReturnInventory(gSaleReturnExchangeOrder));
        }
    }

    // 生成退货单
    public GSaleReturnInventory getGSaleReturnInventory(GSaleReturnExchangeOrder gSaleReturnExchangeOrder) {
        GSaleReturnInventory gSaleReturnInventory = new GSaleReturnInventory();
        BeanUtils.copyProperties(gSaleReturnExchangeOrder, gSaleReturnInventory);
        gSaleReturnInventory.setInventoryType(Constants.ONE_STR);
        gSaleReturnInventory.setIsStatus(Constants.ONE_STR);
        List<SaleReturnInventoryProduct> saleReturnInventoryProductList = new ArrayList<>();
        for (GSaleReturnExchangeOrderDetail gSaleReturnExchangeOrderDetail : gSaleReturnExchangeOrder.getGSaleReturnExchangeOrderDetails()) {
            SaleReturnInventoryProduct saleReturnInventoryProduct = new SaleReturnInventoryProduct();
            BeanUtils.copyProperties(gSaleReturnExchangeOrderDetail, saleReturnInventoryProduct);
            saleReturnInventoryProduct.setProduct(gSaleReturnExchangeOrderDetail.getProductName());
            saleReturnInventoryProduct.setProductCode(gSaleReturnExchangeOrderDetail.getProductCode());
            if (StringUtils.isEmpty(saleReturnInventoryProduct.getProduct()) || StringUtils.isEmpty(saleReturnInventoryProduct.getProductCode())) {
                if (StringUtils.isNotEmpty(gSaleReturnExchangeOrderDetail.getProductId())) {
                    ResultBody<ProductInfo> productById = portalApi.getProductById(gSaleReturnExchangeOrderDetail.getProductId());
                    ProductInfo productInfo = productById.getData();
                    if (productInfo != null) {
                        saleReturnInventoryProduct.setProduct(productInfo.getProductName());
                        saleReturnInventoryProduct.setProductCode(productInfo.getProductCode());
                    }
                }
            }
            saleReturnInventoryProduct.setBatchNumber(gSaleReturnExchangeOrderDetail.getBatchNumber());
            saleReturnInventoryProductList.add(saleReturnInventoryProduct);
            saleReturnInventoryProduct.setId("");
        }
        gSaleReturnInventory.setId("");
        gSaleReturnInventory.setSaleReturnInventoryProductList(saleReturnInventoryProductList);
        return gSaleReturnInventory;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateGSaleReturnExchangeOrder(GSaleReturnExchangeOrder gSaleReturnExchangeOrder) {
        if (CollectionUtils.isEmpty(gSaleReturnExchangeOrder.getGSaleReturnExchangeOrderDetails())) {
            throw new ServiceException(SaleErrorCode.BCP_CP_OUT_BOUND_NO_PRODUCT.getCode(), SaleErrorCode.BCP_CP_OUT_BOUND_NO_PRODUCT.getMsg());
        }

        Map<String, String> aTypeMap = new HashMap<>();
        for (GSaleReturnExchangeOrderDetail saleReturnExchangeOrderDetail : gSaleReturnExchangeOrder.getGSaleReturnExchangeOrderDetails()) {
            if (aTypeMap.get(saleReturnExchangeOrderDetail.getTrayId()) != null) {
                throw new ServiceException(SaleErrorCode.SAME_A_TYPE_DELETE.getCode(), SaleErrorCode.SAME_A_TYPE_DELETE.getMsg());
            }else {
                aTypeMap.put(saleReturnExchangeOrderDetail.getTrayId(),saleReturnExchangeOrderDetail.getTrayId());
            }
        }

        baseMapper.updateById(gSaleReturnExchangeOrder);
        Map<Object, Object> userMap = rediservice.hmget(RedisKey.USER_GROUP_TYPE);
        MaterialProductsOut materialProductsOut = new MaterialProductsOut();

        for (GSaleReturnExchangeOrderDetail gSaleReturnExchangeOrderDetail : gSaleReturnExchangeOrder.getGSaleReturnExchangeOrderDetails()) {
            // 调用物管半成品 成品 出库申请

            materialProductsOut.setOutStorageOrderNo(getMaterialOUTNumber());
            ResultBody<ProductInfo> productById = portalApi.getProductById(gSaleReturnExchangeOrderDetail.getProductId());
            ProductInfo productInfo = productById.getData();
            materialProductsOut.setType(productInfo.getProductType());
            materialProductsOut.setItemName(productInfo.getProductName());
            materialProductsOut.setItemCode(productInfo.getProductCode());
            materialProductsOut.setSpecification(productInfo.getStandard());
            materialProductsOut.setUnit(productInfo.getUnit());
            materialProductsOut.setPreparerId(gSaleReturnExchangeOrder.getCreteUserId());
            materialProductsOut.setPreparer((String) userMap.get(gSaleReturnExchangeOrder.getCreteUserId()));
            materialProductsOut.setQuantity(gSaleReturnExchangeOrderDetail.getReturnQuantity());
            if (gSaleReturnExchangeOrder.getCustomerId() != null) {
                GSaleCustomerManagement gSaleCustomerManagement = saleCustomerManagementMapper.selectById(gSaleReturnExchangeOrder.getCustomerId());
                if (gSaleCustomerManagement != null) {
                    materialProductsOut.setCustomerId(gSaleCustomerManagement.getId());
                    materialProductsOut.setCustomerName(gSaleCustomerManagement.getCustomerName());
                    materialProductsOut.setContractNumber(gSaleCustomerManagement.getCustomerNumber());
                }
            }
            //判断是成品还是半成品
            if (productInfo.getProductType().equals(Constants.TWO_STR)) {
                materialProductsOut.setMenuId(SaleMenuIdCode.MENU_ID_BCPK_OUT.getMsg());
                materialApi.addMaterialBcpOutBound(materialProductsOut);
            } else {
                materialProductsOut.setMenuId(SaleMenuIdCode.MENU_ID_CPK_OUT.getMsg());
                materialApi.addMaterialCpOutBound(materialProductsOut);
            }
        }

    }

    private static final String SALE_OUT_NUMBER = "sale_out_number";

    @RedissonLock(key = MATERIAL_IN_WAREHOUSE_NUMBER, prefixKey = "lock_")
    public String getMaterialOUTNumber() {
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern(CommonConstant.DATE_FORMAT_UN_SEPARATE));
        date = "OUT".concat(date);
        String code = "";

        Serializable number = rediservice.get(RedisKey.MATERIAL_OUT_WAREHOUSE_NUMBER);
        if (number == null || StringUtils.isBlank(number.toString())) {
            ResultBody<String> resultBody = portalApi.getValueByCode(SALE_OUT_NUMBER);
            if (resultBody != null && StringUtils.isNotBlank(resultBody.getData())) {
                number = resultBody.getData();
            }
        }
        if (number != null && StringUtils.isNotBlank(number.toString()) && number.toString().length() > 11) {
            String sequenceStr = number.toString().substring(11);
            int sequenceInt = Integer.parseInt(sequenceStr);
            sequenceInt = sequenceInt + 1;
            String newSequence = String.valueOf(sequenceInt);
            if (newSequence.length() == CommonConstant.FIVE_INT) {
                code = date.concat("0001");
            } else {
                code = date.concat(String.format("%04d", sequenceInt)); // 格式化数字为4位，不足部分用0填充
            }
        } else {
            code = date.concat("0001");
        }
        rediservice.set(RedisKey.MATERIAL_OUT_WAREHOUSE_NUMBER, code);
        DictInfo info = new DictInfo();
        info.setCsdm(RedisKey.MATERIAL_OUT_WAREHOUSE_NUMBER);
        info.setCsmc(code);
        portalApi.updateValueByCode(info);
        return code;
    }


    @Override
    public GSaleReturnExchangeOrder getGSaleReturnExchangeOrderOne(String id) {
        GSaleReturnExchangeOrder gSaleReturnExchangeOrder = baseMapper.selectById(id);
        List<GSaleReturnExchangeOrderDetail> gSaleReturnExchangeOrderDetails = gSaleReturnExchangeOrderDetailMapper.selectList(Wrappers.<GSaleReturnExchangeOrderDetail>lambdaQuery()
                .eq(GSaleReturnExchangeOrderDetail::getReturnId, id));
        gSaleReturnExchangeOrder.setGSaleReturnExchangeOrderDetails(gSaleReturnExchangeOrderDetails);
        ResultBody<List<String>> fileIdsByBusinessId = fileApi.getFileIdsByBusinessId(id);
        if (fileIdsByBusinessId != null) {
            gSaleReturnExchangeOrder.setFilesIds(fileIdsByBusinessId.getData());
        }
        return gSaleReturnExchangeOrder;
    }

}
